#! /usr/bin python
# -*- coding: utf-8 -*-
# author: captjack
# python 2.7.5
# multipart redis node stat

import datetime
import socket

# ops_array、keys_array、clients_array
import time

stat_dict = {
    "ops": [],
    "clients": [],
    "keys": []
}


# receive_all
def receive_all(s):
    result = ""
    while True:
        tmp = s.recv(521 * 16)
        result += tmp
        if tmp.endswith("\r\n"):
            break
    return result


# 执行redis命令
def execute_redis_command(redis_host, redis_port, command, password="pass"):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 连接
    s.connect((redis_host, redis_port))
    # 鉴权
    s.send("auth " + password + "\r\n")
    receive_all(s)
    # 拉取信息
    s.send(command + "\r\n")
    # 读取返回信息
    result = receive_all(s)
    # close
    s.close()
    # return
    return result


# 执行统计
def stat(redis_info):
    # 执行各种统计
    lines = str(redis_info).split("\r\n")
    # 追加-1，增加容错
    for k, v in stat_dict.items():
        v.append(-1)
    # 统计
    for line in lines:
        # ops
        if "instantaneous_ops_per_sec" in line:
            stat_dict['ops'][-1] = int(line[line.index(":") + 1:])
        # keys
        elif ":keys=" in line:
            stat_dict['keys'][-1] = int(line[line.index("=") + 1:line.index(",")])
        # connected_clients
        elif "connected_clients:" in line:
            stat_dict['clients'][-1] = int(line[line.index(":") + 1:])
        else:
            pass


# 打印统计信息
def print_stat_info(address_array):
    current = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print "\n************************************" + current + "***********************************************"
    print "---------------------------------------------- detail info -----------------------------------------"
    # 打印明细信息
    print "{0:^21}\t{1:^15}\t{2:^15}\t{3:^15}".format("address", "ops", "keys", "clients")
    for index, addr in enumerate(address_array):
        print "{0:^21}\t{1:^15}\t{2:^15}\t{3:^15}".format(
            addr, stat_dict['ops'][index], stat_dict['keys'][index], stat_dict['clients'][index])
    print "{0:^21}\t{1:^15}\t{2:^15}\t{3:^15}".format("address", "ops", "keys", "clients")
    print "------------------------------------------------ stat info -----------------------------------------"
    # 打印统计信息
    print "{0:^10}\t{1:^15}\t{2:^15}\t{3:^15}\t{4:^15}".format("stat type", "total", "avg", "max", "min")
    for k, v in stat_dict.items():
        print "{0:^10}\t{1:^15}\t{2:^15}\t{3:^15}\t{4:^15}".format(k, sum(v), sum(v) / v.__len__(), max(v), min(v))
    print "************************************" + current + "***********************************************"


# 处理多个redis节点
def execute_for_node(address_array, password):
    for address in address_array:
        # 解析出ip和port
        ip = address[0:address.index(":")]
        port = int(address[address.index(":") + 1:])
        # 请求
        redis_info = execute_redis_command(ip, port, "info", password)
        # 执行统计
        stat(redis_info)
        # sleep
        time.sleep(0.01)
        # 打印统计信息
    print_stat_info(address_array)


# 解析集群信息，返回所有节点的地址信息
def explain_cluster_node_info(cluster_info):
    # 执行各种统计
    lines = str(cluster_info).split("\n")
    # 返回结果
    node_addr_list = []
    #
    for line in lines:
        if "@" in line:
            node_addr_list.append(line[line.index(" "):line.index("@")])
    return node_addr_list


# 集群模式
def execute_for_cluster():
    password = "password"
    cluster_node_info = execute_redis_command("127.0.0.1", 7001, "cluster nodes", password)
    #
    address_array = explain_cluster_node_info(cluster_node_info)
    # 执行统计
    execute_for_node(address_array, password)


# 入口
if __name__ == '__main__':
    execute_for_cluster()
